// 基础节点，其他节点在此基础上扩展

import itemEvents from './item-event';
import anchorEvent from './anchor-event';

export default G6 => {
    G6.registerNode('base-node', {
        // 绘制图标
        drawIcon(cfg, group, attrs) {

        },
        // 初始化锚点
        initAnchor(cfg, group) {
            // 锚点图形
            group.anchorShapes = [];
            // 显示锚点
            group.showAnchor = group => {
                this.drawAnchor(cfg, group);
            }
            // 隐藏锚点
            group.clearAnchor = group => {
                if (group.anchorShapes) {
                    group.anchorShapes.forEach(anchor => anchor.remove());
                }
                group.anchorShapes = [];
            }
        },
        // 绘制锚点
        drawAnchor(cfg, group) {
            const keyShape = group.getFirst();
            const { type, direction, anchorPointStyles } = keyShape.attr();
            const node = group.get('item');
            const bBox = keyShape.getBBox();
            // 获取配置锚点
            const anchors = this.getAnchorPoints(cfg) || [];
            if (anchors.length) {
                anchors.forEach((anchorCfg, i) => {
                    const x = bBox.width * (anchorCfg[0] - 0.5);
                    const y = bBox.height * (anchorCfg[1] - 0.5);
                    // 绘制三层锚点
                    // 最底层：锚点背景
                    // 中间层：锚点
                    // 最顶层：锚点group，用于事件触发
                    const anchor = group.addShape('circle', {
                        attrs: {
                            x,
                            y,
                            ...anchorPointStyles
                        },
                        zIndex: 1,
                        className: 'node-anchor',
                        nodeId: node.get('id'),
                        draggable: true,
                        isAnchor: true,
                        index: i // 方便查找锚点
                    })
                    const anchorGroup = group.addShape('circle', {
                        attrs: {
                            x,
                            y,
                            r: 11,
                            fill: '#000',
                            opacity: 0
                        },
                        zIndex: 2,
                        className: 'node-anchor-group',
                        nodeId: node.get('id'),
                        draggable: true,
                        isAnchor: true,
                        index: i
                    })
                    // 添加绑定锚点事件，给最上层的group添加事件
                    anchorEvent(anchorGroup, group, anchorCfg);

                    // 锚点放到组中
                    group.anchorShapes.push(anchor);
                    group.anchorShapes.push(anchorGroup);
                })
                // 查找所有锚点
                group.getAllAnchors = () => {
                    return group.anchorShapes.filter(c => c.get('isAnchor') === true);
                }
                // 查找指定锚点
                group.getAnchor = i => {
                    return group.anchorShapes.filter(c => c.get('className') === 'node-anchor' && c.get('index') === i);
                }
                // 查找所有锚点背景
                group.getAllAnchorBg = () => {
                    return group.anchorShapes.filter(c => c.get('className') === 'node-anchor-bg');
                };
            }
        },
        // 绘制label文本
        drawLabel(cfg, group, attrs) {
            const { label, labelCfg, labels } = attrs;
            // 多行文本
            if (labels) {
                labels.forEach(item => {
                    const { label, labelCfg: { maxLength }, className } = item;
                    // 文本长度
                    let text = maxLength ? label.substr(0, maxLength) : label || '';
                    if (label.length > maxLength) {
                        text = `${text}...`;
                    }
                    group.addShape('text', {
                        attrs: {
                            text,
                            ...item,
                            ...item.labelCfg
                        },
                        className: `node-text ${className}`,
                        draggable: true
                    })
                })
            // 单行文本
            } else if (label) {
                const { maxLength } = labelCfg;
                // 超出显示...
                let text = maxLength ? label.substr(0, maxLength) : label || '';
                if (label.length > maxLength) {
                    text = `${text}...`;
                }
                group.addShape('text', {
                    attrs: {
                        text,
                        x: 0,
                        y: 0,
                        ...label,
                        ...labelCfg
                    },
                    className: 'node-text',
                    draggable: true
                })
            }
        },
        // 绘制节点和文本
        draw(cfg, group) {
            // 获取图形样式
            const attrs = this.getShapeStyle(cfg, group);
            const keyShape = group.addShape(this.shapeType, {
                className: `${this.shapeType}-shape`, // rect-shape
                draggable: true,
                attrs
            })
            // 通过class查找元素
            group.getItem = className => {
                return group.get('children').find(item => item.get('className') === className);
            }
            // 绘制文本节点
            this.drawLabel(cfg, group, attrs);
            // 添加锚点
            this.initAnchor(cfg, group);
            
            return keyShape;
        },
        // 更新节点和文本
        update(cfg, node) {
            
        },
        // 设置节点状态，主要是交互状态，业务状态在draw方法中实现（定义此方法，实例中配置的状态会失效）
        setState(name, value, item) { // name =>'nodeState hover' , value => true , item => Node
            const activeEvents = [
                'anchorShow', // 锚点显示隐藏
                'anchorActive', // 鼠标按下锚点，让所有node的锚点处于激活状态
                'nodeState', // nodeState:xxx都会触发nodeState事件
                'nodeState:default',
                'nodeState:hover',
                'nodeState:selected'
            ];
            const group = item.getContainer(); // 获取容器
            if (group.get('destroyed')) return; // 组已经卸载
            if (activeEvents.includes(name)) {
                // this指向当前实例
                // 调用对应更新状态的方法
                itemEvents[name].call(this, value, group);
            } else {
                console.warn(`warning: ${name} 事件回调未注册`);
            }
        },
        // 锚点配置
        getAnchorPoints(cfg) {
            return cfg.anchorPoints || [
                [0.5, 0],
                [1, 0.5],
                [0.5, 1],
                [0, 0.5]
            ]
        }
    }, 'single-node');
}